/**
 * 
 */
package com.desksoft.ecommerce.jms;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.desksoft.ecommerce.util.holder.ApplicationContextHolder;
import com.desksoft.utility.jms.MessageProducer;
import com.desksoft.utility.resource.ResourceUtil;
import com.desksoft.utility.string.StringUtil;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Sets;

/***************************************
 * <pre>
 * 版权所有：杭州迪科软件 保留所有权利
 * 创建日期: Nov 9, 2011 2:19:13 PM
 * 创建作者：yejw
 * 文件名称：NotifyServFactory.java
 * 版本：1.0
 * 功能：消息服务通道在  /00.DESKSOFT_COMMON/src/notify_pipe.properties 配置文件中定义.
 * 最后修改时间：Nov 9, 2011 2:19:13 PM
 * 修改记录：
 * </pre>
 *****************************************/
public class NotifyServFactory {
	
	protected final static Log log = LogFactory.getLog(NotifyServFactory.class);

	/**
	 * 
	 */
	private NotifyServFactory() {}
	
	/**
	 * Notify Pipes Define
	 */
	private static BiMap<String, String> NOTIFY_PIPES_DEFINE = null;  
	
	static {
		NOTIFY_PIPES_DEFINE = HashBiMap.create();
		intlNotifyPipesDefine();
	}
	
	/**
	 * 获取消息服务工厂实例
	 * 
	 * @return NotifyServFactory
	 */
	public static NotifyServFactory getInstance() {
		return NotifyServFactoryHolder.INSTANCE;
	}

//	/**
//	 * 发送消息
//	 * 
//	 * @param <T>
//	 * @param message	消息
//	 */
//	public <T> void send(T message) {
//		checkNotNull(message, "The message is not defined!");
//		
//		this.getMessageProducer(message).sendMessage(message);
//	}
	
	/**
	 * Notify Service Factory
	 */
	private static class NotifyServFactoryHolder {
		private final static NotifyServFactory INSTANCE = new NotifyServFactory();
    }

	/* (non-Javadoc)
	 * @see java.lang.Object#clone()
	 */
	@Override
	protected Object clone() throws CloneNotSupportedException {
		throw new CloneNotSupportedException();
	}
	
	/**
	 * Get Message Producer
	 * 
	 * @param notify
	 * @return
	 */
	private MessageProducer getMessageProducer(Object notify) {
		String name = notify.getClass().getName(),
		tip = "Unknown message! Please configure the corresponding message service channel!";
		
		checkArgument(NOTIFY_PIPES_DEFINE.containsKey(name), StringUtil.join(tip, name));
		
		MessageProducer producer = (MessageProducer) ApplicationContextHolder.getBean(NOTIFY_PIPES_DEFINE.get(name));
		checkNotNull(producer, StringUtil.join("Unknown message service!", name, ": ", NOTIFY_PIPES_DEFINE.get(name)));
		
		return producer;
	}

	/**
	 * Initialize notify pipes define
	 */
	private static void intlNotifyPipesDefine() {
		String msginst = "notify.pipe.%s.msginst", producer = "notify.pipe.%s.producer";
		Properties props = ResourceUtil.getResourceAsProperties("notify_pipe.properties");
		
		Set<String> names = getNames(props);
		checkArgument(names.size() > 0, notifyPipeUndefined);
		
		for (String name : names) {
			NOTIFY_PIPES_DEFINE.put(
				props.getProperty(String.format(msginst, name)), 
				props.getProperty(String.format(producer, name))
			);
		}
	}

	/**
	 * Get notify pipes name
	 * 
	 * @param props 
	 * @return
	 */
	private static Set<String> getNames(Properties props) {
		checkNotNull(props);
		checkArgument(props.size() > 0, notifyPipeUndefined);
		
		Matcher matcher = null;
		Set<String> names = Sets.newHashSet();
		Pattern pattern = Pattern.compile("(?<=notify\\.pipe\\.).*(?=\\.msginst|\\.producer)");
		
		for (Object o : props.keySet()) {
			if (o == null) {
				continue;
			}
			
			String key = null;
			matcher = pattern.matcher((String) o);
			if (matcher.find()) {
				key = matcher.group(0);
			}
			
			if (key == null || names.contains(key)) {
				continue;
			}
			
			names.add(key);
		}
		
		return names;
	}
	
	/**
	 * Undefined message
	 */
	private static String notifyPipeUndefined = "\u672a\u5b9a\u4e49\u6d88\u606f\u670d\u52a1\u901a\u9053!";
	
}
